import 'package:flutter/material.dart';

// 事件回调
// typedef ButtonCallback = void Function(MyButtons button);
typedef ButtonCallback = VoidCallback;

// 按钮类型
// ignore: constant_identifier_names
enum ButtonType { DEFAULT, PRIMARY, SUCCESS, INFO, WARN, DANGER }

class MyButtons extends StatefulWidget {
  final String text; // 按钮文字
  final TextStyle? style; // 文字样式
  final EdgeInsets? margin; // 按钮外间距
  final EdgeInsets? padding; // 按钮内间距
  final Widget? icon; // 按钮的图标
  final Border? border; // 按钮边框
  final BorderRadius? radius; // 按钮的圆角
  final ButtonType type; // 按钮类型
  final ButtonCallback? onTap; // 按钮的点击事件

  const MyButtons({
    super.key,
    required this.text,
    this.style,
    this.margin,
    this.padding,
    this.icon,
    this.border,
    this.radius,
    this.type = ButtonType.DEFAULT, // 这里给它一个默认类型
    this.onTap,
  });

  @override
  State<MyButtons> createState() => _ButtonState();
}

class _ButtonState extends State<MyButtons> {
  Color? _bgColor; // 当前按钮的背景颜色
  Color? _textColor; // 对应的文字颜色

  @override
  void initState() {
    super.initState();
    _switchStyle(active: false);
  }

  @override
  void didUpdateWidget(MyButtons oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.type != widget.type) {
      _switchStyle(active: false);
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _switchStyle(active: false);
  }

  @override
  Widget build(BuildContext context) {
    // 按钮的核心内容
    Widget body = DefaultTextStyle(
      style: TextStyle(color: _textColor),
      child: Text(widget.text, style: widget.style),
    );

    // 如果外部提供了按钮图标，则更改核心内容布局
    if (widget.icon != null) {
      body = Row(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 图标（带默认样式）
          IconTheme(
            data: IconThemeData(color: _textColor),
            child: widget.icon!,
          ),
          const SizedBox(width: 5), // 5 像素的左右间隔
          // 按钮文本
          body,
        ],
      );
    }

    // 按钮的动态样式
    BoxDecoration decoration = BoxDecoration(
      border: widget.border,
      boxShadow: [
        BoxShadow(
          color: _bgColor!.withAlpha(120),
          blurRadius: 10,
          offset: const Offset(0, 5),
          spreadRadius: 1,
        ),
      ],
      borderRadius: widget.radius ?? BorderRadius.circular(100),
      color: _bgColor,
    );

    // 按钮的外层容器
    body = Container(
      decoration: decoration,
      padding:
          widget.padding ??
          const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
      margin: widget.margin,
      child: body,
    );

    // 监听点击事件
    return GestureDetector(
      onTapDown: (e) => _switchStyle(active: true),
      onTapUp: (e) => _resetStyle('up'),
      onTapCancel: () => _resetStyle('cancel'),
      child: body,
    );
  }

  // 当点击事件取消或者抬起时恢复按钮的初始状态
  void _resetStyle(String type) {
    // delayed 是为了让按钮在快速点击的场景下也响应对应色彩变化
    // 否则直接更新UI的话，变化的时间太短暂，肉眼根本看不到。
    Future.delayed(const Duration(milliseconds: 100), () {
      _switchStyle(active: false);
      if (type == 'up') {
        widget.onTap?.call();
      }
    });
  }

  // 动态选择当前状态下的按钮应该渲染什么样的颜色以及样式
  void _switchStyle({required bool active}) {
    switch (widget.type) {
      case ButtonType.DEFAULT:
        _bgColor = active ? Colors.grey[800] : Colors.grey[900];
        _textColor = Colors.white;
        break;
      case ButtonType.PRIMARY:
        _bgColor = active ? Colors.blueAccent[400] : Colors.blueAccent[700];
        _textColor = Colors.white;
        break;
      case ButtonType.SUCCESS:
        _bgColor = active ? Colors.green[800] : Colors.green[900];
        _textColor = Colors.white;
        break;
      case ButtonType.INFO:
        _bgColor = active ? Colors.cyan[800] : Colors.cyan[900];
        _textColor = Colors.white;
        break;
      case ButtonType.WARN:
        _bgColor = active ? Colors.yellow[800] : Colors.yellow[900];
        _textColor = Colors.white;
        break;
      case ButtonType.DANGER:
        _bgColor = active ? Colors.red[400] : Colors.red[700];
        _textColor = Colors.white;
        break;
    }
    if (super.mounted) {
      super.setState(() {});
    }
  }
}
